﻿using System;
using System.Collections.Generic;
using System.Text;
using CommonClasses;
using Eco.ObjectRepresentation;
using Descriptions_DomainModel.Model;
using System.IO;

/*
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using CommonClasses;
    using Descriptions_DomainModel.Model;
    using Descriptions_PinsDescription.Model;
    using Eco.ObjectRepresentation;
    using Eco.Services;
    using CommonClasses.Utility;
    using System.Xml.Serialization;
    using System.IO;
    using CommonClasses.Model;
     */

namespace StoveSupervisor
{

    /// <summary>
    /// Управляющая сборка, осуществляющая работу с MP11 по виртуальным пинам
    /// </summary>
    public class StoveSupervisor : IConnection
    {
        #region Private fields

        /// <summary>
        /// Диспетчер соединений
        /// </summary>
        private IConnection connectionDispatcher;

        /// <summary>
        /// Пин состояния
        /// </summary>
        private StatePinDefinition statePin;

        /// <summary>
        /// Провайдер сервисов ECO
        /// </summary>
        private IEcoServiceProvider serviceProvider;

        /// <summary>
        /// Список выходных пинов
        /// </summary>
        private List<int> outPins;

        string name;

        #endregion

        /// <param name="serviceProvider">Провайдер сервисов ECO</param>
        /// <param name="nodeGroup">узел, который будет управляться данным супервизором</param>
        /// <param name="connectionDispatcher">Диспетчер подключений</param>        
        public StoveSupervisor(IEcoServiceProvider serviceProvider, Node node, IConnection connectionDispatcher)
        {
            name = Path.GetFileNameWithoutExtension(node.Name);

            if (connectionDispatcher == null)
                throw new NullReferenceException("ConnectionDispatcher cannot be null!");

            this.serviceProvider = serviceProvider;
            this.connectionDispatcher = connectionDispatcher;

            statePin = new StatePinDefinition(node.StatePinNumber, node.StatePinMin, node.StatePinMax, 0);
            outPins = new List<int>();
            foreach (Method meth in node.Methods)
            {
                if (!outPins.Contains(meth.VirtualPinOut))
                    outPins.Add(meth.VirtualPinOut);
            }

            SubscribeToConnections();

            Console.WriteLine("StoveSupervisor created");
        }


        #region Configuring

        /// <summary>
        /// Подписаться на изменения пина у соединений
        /// </summary>
        private void SubscribeToConnections()
        {
            connectionDispatcher.OnPinStateChanged += new PinStateChangedHandler(OnPinStateChangedHandler);
        }

        /// <summary>
        /// Снять подписку на изменение пина у соединения
        /// </summary>
        private void DetachSubscription()
        {
            connectionDispatcher.OnPinStateChanged -= new PinStateChangedHandler(OnPinStateChangedHandler);
        }

        #endregion


        #region IConnection Members

        /// <summary>
        /// Событие: изменился входной пин
        /// </summary>
        public event PinStateChangedHandler OnPinStateChanged;

        public void OnPin(int virtualPinOut, int signal)
        {
            if (outPins.Contains(virtualPinOut))
            {
                Console.WriteLine("{0}.OnPin({1},{2})", name, virtualPinOut, signal);
                if (!((signal == 0) || (signal == 1)))
                    return;
                connectionDispatcher.OnPin(virtualPinOut, signal);
            }
            //else Console.WriteLine("{0}:!(outPins.Contains(virtualPinOut)), {1}", name, virtualPinOut.ToString());
        }

        public void FlushPins()
        {
            Console.WriteLine("StoveSupervisor.FlushPins ");
        }

        public void Dispose()
        {
            Console.WriteLine("StoveSupervisor.Dispose ");
            DetachSubscription();
        }

        #endregion

        /// <summary>
        /// Обработка сигналов с датчиков (обрабатываются только еденицы)
        /// </summary>
        /// <param name="virtualPin">изменившийся вирт. пин</param>
        /// <param name="newState">значение на пине</param>
        private void OnPinStateChangedHandler(int virtualPin, int newState)
        {
            //Console.WriteLine("<{0}.OnPinStateChanged>: {1}:{2}", name, virtualPin, newState);            
            statePin.Value = Math.Max(statePin.Min, Math.Min(newState, statePin.Max));
            Console.WriteLine("<{0}.OnPinStateChanged>:  ({1},{2})", name, statePin.PinNumber, statePin.Value);
            if (OnPinStateChanged != null)
                OnPinStateChanged(statePin.PinNumber, statePin.Value);
            //else нас отписали на событие, т.к. реальное соединение не используется
        }
    }

}
